﻿using Max.PH5_2010A.Shopping.DTO;
using Max.PH5_2010A.Shopping.IService;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Max.PH5_2010A.Shopping.API.Controllers
{
    /// <summary>
    /// 购物车控制器
    /// </summary>
    [Route("car")]
    [ApiController]
    public class ShoppingCarController : ControllerBase
    {
        /*
         * 在VS中使用Redis做为购物车
         * 1、安装包 CsRedisCore
         * 2、连接到Redis服务器(创建一个redis客户端)
         * 
         * **/
        CSRedis.CSRedisClient _client;
        IProductSkuService _skuService;
        /// <summary>
        /// 构造函数（初始化值）
        /// </summary>
        public ShoppingCarController(IProductSkuService skuService)
        {
            _client = new CSRedis.CSRedisClient("127.0.0.1:6379");
            _skuService = skuService;
        }

        /// <summary>
        /// 添加购物车
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Post(ShoppingCarDto dto)
        {
            //return Ok("添加成功");
            ResponseResultDto result = new();
            string key = dto.Key;

            #region 判断库存
            //要添加到购物车中的商品即dto中的商品数量和这个商品的库存数量进行比较
            //我们定义的dto中是商品的集合，但添加的时候，每次就一个商品，所以单独拿出来处理
            var _data = dto.Values[0];
            //拿这个商品的库存-------从商品的SKU表获取
            var _model = _skuService.Select().Where(x => x.Id.ToString().Equals(_data.ProductId)).FirstOrDefault();

            //进行比较(购买的数量不能大于库存中可用的库存数量)
            if (_data.ProductNumber > _model.ValidStock)
            {
                //库存不足
                result.Code = ResponseResultCode.StockError;
                result.Message = "库存不足";
                return Ok(result);
            }
            #endregion

            if (!_client.Exists(key))
            {
                //如果不存在，说明redis服务器中，都是空的（没有你这个key的数据）,可以直接将要添加的商品数据放进去
                _client.Set(key, dto.Values);
            }
            else
            {
                //先将这个用户的购物车中的商品，从内存redis拿出来
                var data = _client.Get<List<ShoppingCarProductInfoDto>>(key);

                //这拿出来的数据中，再去判断，是否包含这个即将添加进去的商品

                //正常界面上点击添加按钮的时候，一次只能添加一种商品，在定义dto的时候，是一个用户对应多种商品，所以用下标取第一个商品
                var first = dto.Values[0];

                var m = data.Where(x => x.ProductId.Equals(first.ProductId)).FirstOrDefault();
                //找没有找到，只需要判断data即可
                if (m == null)
                {
                    //说明原来购物车没有这个商品
                    data.Add(first);
                }
                else
                {
                    #region 库存判断
                    //这个要添加的商品数量和这个商品原来在购物车中数量之和，不能大于这个商品的库存数量
                    var number = first.ProductNumber + m.ProductNumber;
                    var d = _skuService.Select().Where(x => x.Id.ToString().Equals(first.ProductId)).FirstOrDefault();
                    if (number > d.ValidStock)
                    {
                        //库存不足
                        result.Code = ResponseResultCode.StockError;
                        result.Message = "库存不足";
                        return Ok(result);
                    }
                    #endregion

                    //原来购物车，有这个商品，则数量累加
                    m.ProductNumber += first.ProductNumber;
                }

                //hash:{key,value}
                //key : {key,value}
                //_client.HSet()

                _client.Set(key, data);
            }
            return Ok(result);
        }

        /// <summary>
        /// 获取购物车
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Get(string key)
        {
            ResponseResultDto result = new();

            if (_client.Exists(key))
            {
                //先将这个用户的购物车中的商品，从内存redis拿出来
                var data = _client.Get<List<ShoppingCarProductInfoDto>>(key);

                data.ForEach(x => {
                    var m = _skuService.Select().Where(p => p.Id.ToString().Equals(x.ProductId)).FirstOrDefault();
                    if(x.ProductNumber > m.ValidStock)
                    {
                        x.StockError = true;
                    }
                });

                result.Data = data;
                return Ok(result);
            }
            else
            {
                result.Code = ResponseResultCode.ValidKey;
                result.Message = "无效Key";
                return Ok(result);

            }
        }

        /// <summary>
        /// 修改购物车
        /// </summary>
        /// <returns></returns>
        [HttpPut]
        public IActionResult Put(ShoppingCarDto dto)
        {
            ResponseResultDto result = new();
            string key = dto.Key;

            if (!_client.Exists(key))
            {
                result.Code = ResponseResultCode.Failed;
                result.Message = "无效Key";
                return BadRequest(result);
            }

            //先从redis中拿出数据
            var data = _client.Get<List<ShoppingCarProductInfoDto>>(key);
            if (data == null || data.Count <= 0)
            {
                result.Code = ResponseResultCode.Failed;
                result.Message = "无效数据";
                return BadRequest(result);
            }

            var first = dto.Values[0]; //要修改的数据，界面上一次只能点击一种商品

            //根据商品ID，去拿出来的数据中，找到要修改数量的商品
            var m = data.Where(x => x.ProductId.Equals(first.ProductId)).FirstOrDefault();

            if (m != null)
            {

                #region 库存判断
                //这个要添加的商品数量和这个商品原来在购物车中数量之和，不能大于这个商品的库存数量
                var number = first.ProductNumber;
                var d = _skuService.Select().Where(x => x.Id.ToString().Equals(first.ProductId)).FirstOrDefault();
                if (number > d.ValidStock)
                {
                    //库存不足
                    result.Code = ResponseResultCode.StockError;
                    result.Message = "库存不足";
                    return Ok(result);
                }
                #endregion

                m.ProductNumber = first.ProductNumber;

                //如果修改的商品的数量小于等于0，这样的商品放在redis就没意义
                if (m.ProductNumber <= 0)
                {
                    data.Remove(m);
                }
            }

            _client.Set(key, data);

            return Ok(result);
        }

        /// <summary>
        /// 删除购物车
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete]
        public IActionResult Delete(ShoppingCarDto dto)
        {
            ResponseResultDto result = new();
            string key = dto.Key;

            if (!_client.Exists(key))
            {
                result.Code = ResponseResultCode.ValidKey;
                result.Message = "无效Key";
                return Ok(result);
            }

            //先从redis中拿出数据
            var data = _client.Get<List<ShoppingCarProductInfoDto>>(key);
            if (data == null || data.Count <= 0)
            {
                result.Code = ResponseResultCode.Failed;
                result.Message = "无效数据";
                return BadRequest(result);
            }

            dto.Values.ForEach(x =>
            {
                var m = data.Where(p => p.ProductId.Equals(x.ProductId)).FirstOrDefault();
                if (m != null)
                {
                    data.Remove(m);
                }
            });

            if (data.Count <= 0)
            {
                //表示所有的数据都删除了，这个key留着也没意义了
                _client.Del(key);
            }
            else
            {
                _client.Set(key, data);
            }

            return Ok(result);
        }
    }
}
